/*
Copyright 2010,2011 Matt Van Der Westhuizen

This file is part of CGLL.

CGLL is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CGLL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with CGLL.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.chaoticengine.cgll;

import org.chaoticengine.cgll.camera.Camera;
import org.chaoticengine.cgll.entity.EntityManager;
import org.chaoticengine.cgll.input.InputManager;
import org.chaoticengine.cgll.twl.RootPane;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

/**
 * A Slick2D GameState for CGLL - extend to create a CGLL game.
 *
 * @author Matt v.d. Westhuizen
 */
public abstract class CGLLGameState extends BasicGameState {
    protected EntityManager entityMgr = null;
    protected InputManager inputMgr = null;
    protected Camera camera = null;
    protected RootPane rootPane = null;

    protected int frameSkip = 0;
    protected int framesSkipped = 0;

    public CGLLGameState(boolean hasGUI) {
        if (hasGUI) {
            rootPane = new RootPane(this);
        }
    }

    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
        entityMgr = new EntityManager();
        
        camera = new Camera();
        camera.setPosition(new Vector2f(0.0f, 0.0f));
        camera.setBoundingRectangle(new Rectangle(0.0f, 0.0f, gc.getWidth(), gc.getHeight()));
        camera.setViewport(new Rectangle(0.0f, 0.0f, gc.getWidth(), gc.getHeight()));
        
        inputMgr = new InputManager(entityMgr);
        gc.getInput().addKeyListener(inputMgr);
        gc.getInput().addMouseListener(inputMgr);
    }

    @Override
    public void enter(GameContainer container, StateBasedGame game) throws SlickException {
        super.enter(container, game);

        ((CGLLStateBasedGame) game).handleStateChange();
    }

    public void render(GameContainer gc, StateBasedGame sbg, Graphics grphcs) throws SlickException {
        // Do transforms for the camera
        camera.renderBefore(gc, sbg, grphcs);

        // Render entities
        entityMgr.render(gc, sbg, grphcs);

        // Do transforms for the camera
        camera.renderAfter(gc, sbg, grphcs);
    }

    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
        if (frameSkip != 0) {
            if (framesSkipped != frameSkip) {
                framesSkipped++;
                return;
            } else {
                framesSkipped = 0;
            }
        }

        // First destroy destroyed entities so they don't update
        entityMgr.destroyEntities();

        // Update the camera
        camera.update(gc, sbg, delta);

        // Update all entities
        entityMgr.update(gc, sbg, delta);

        // Do collision detection and handling
        entityMgr.doCollisions();
    }

    public EntityManager getEntityManager() {
        return(entityMgr);
    }

    public Camera getCamera() {
        return(camera);
    }

    public InputManager getInputManager() {
        return(inputMgr);
    }

    public void setFrameSkip(int fs) {
        frameSkip = fs;
    }

    public RootPane getRootPane() {
        return rootPane;
    }

    public void setRootPane(RootPane rootPane) {
        this.rootPane = rootPane;
    }

    public void keyboardFocusLost() {
    }

    public void layoutRootPane() {
        rootPane.setPosition(0, 0);
    }
}
